package TestTime;

import java.awt.Label;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

/**
 * 判断身份证信息
 *
 * @author 刘胜军
 */
public class Go extends JFrame {

	private static final long serialVersionUID = 1L;

	/**
	 * 保存全国各地区身份证代码
	 */
	private static Map<Integer, String> city = new HashMap<Integer, String>();

	/**
	 * 定义八个标签
	 */
	private Label IDTitle = new Label("用 户  I D：");
	private Label areaTitle = new Label("所属地区：");
	private Label birthdayTitle = new Label("出生日期：");
	private Label ageTitle = new Label("年    龄    ：");
	private Label constellationTitle = new Label("星    座    ：");
	private Label animalTitle = new Label("生    肖    ：");
	private Label CETitle = new Label("天干地支：");
	private Label sexTitle = new Label("性    别    ：");
	private Label coefficientTitle = new Label("校  验  位：");

	/**
	 * 定义八个文本框
	 */
	private JTextField ID = new JTextField("522634520829128");
	private JTextField area = new JTextField();
	private JTextField birthday = new JTextField();
	private JTextField age = new JTextField();
	private JTextField constellation = new JTextField();
	private JTextField animal = new JTextField();
	private JTextField CE = new JTextField();
	private JTextField sex = new JTextField();
	private JTextField coefficient = new JTextField();

	/**
	 * 定义一个按钮
	 */
	private JButton send = new JButton("提交");

	/**
	 * 主函数
	 *
	 * @param args
	 */
	public static void main(String[] args) {
		Go go = new Go();
		go.init();
	}

	/**
	 * 初始化函数
	 */
	public void init() {
		areaInsert();// 插入所属地区信息库
		frame_init();// 界面初始化函数
	}

	/**
	 * 界面初始化函数
	 */
	public void frame_init() {
		this.setTitle("身份证信息");// 设置窗体标题
		this.setBounds(400, 200, 300, 450);// 位置坐标
		this.setLayout(null);// 取消布局方式

		/** 设置九个标签坐标位置及大小 */
		this.IDTitle.setBounds(20, 27, 80, 20);
		this.areaTitle.setBounds(20, 67, 80, 20);
		this.birthdayTitle.setBounds(20, 107, 80, 20);
		this.ageTitle.setBounds(20, 147, 80, 20);
		this.constellationTitle.setBounds(20, 187, 80, 20);
		this.animalTitle.setBounds(20, 227, 80, 20);
		this.CETitle.setBounds(20, 267, 80, 20);
		this.sexTitle.setBounds(20, 307, 80, 20);
		this.coefficientTitle.setBounds(20, 347, 80, 20);

		/** 设置九个文本框坐标位置及大小 */
		this.ID.setBounds(120, 27, 150, 20);
		this.area.setBounds(120, 67, 150, 20);
		this.birthday.setBounds(120, 107, 150, 20);
		this.age.setBounds(120, 147, 150, 20);
		this.constellation.setBounds(120, 187, 150, 20);
		this.animal.setBounds(120, 227, 150, 20);
		this.CE.setBounds(120, 267, 150, 20);
		this.sex.setBounds(120, 307, 150, 20);
		this.coefficient.setBounds(120, 347, 150, 20);

		/** 设置按钮坐标位置及大小 */
		this.send.setBounds(100, 390, 100, 20);

		/** 设置其他八个文本框为不可编辑状态 */
		this.area.setEditable(false);
		this.birthday.setEditable(false);
		this.age.setEditable(false);
		this.constellation.setEditable(false);
		this.animal.setEditable(false);
		this.CE.setEditable(false);
		this.sex.setEditable(false);
		this.coefficient.setEditable(false);

		/** 将九个标签添加到窗体上 */
		this.add(IDTitle);
		this.add(areaTitle);
		this.add(birthdayTitle);
		this.add(ageTitle);
		this.add(constellationTitle);
		this.add(animalTitle);
		this.add(CETitle);
		this.add(sexTitle);
		this.add(coefficientTitle);

		/** 将九个文本框添加到窗体上 */
		this.add(ID);
		this.add(area);
		this.add(birthday);
		this.add(age);
		this.add(constellation);
		this.add(animal);
		this.add(CE);
		this.add(sex);
		this.add(coefficient);

		/** 将按钮添加到窗体上 */
		this.add(send);

		this.ID.addKeyListener(new KeyAdapter() {
			@Override
			public void keyTyped(KeyEvent e) {// 判断输入是不是数字或X，不是数字不让输入
				char keyChar = e.getKeyChar();
				if ((keyChar == 'x') || (keyChar == 'X') || (keyChar >= KeyEvent.VK_0 && keyChar <= KeyEvent.VK_9)) {
					;
				} else {
					e.consume();
				}
				/** 以下几行，当重新输入身份证号的时候，其他文本框清空 */
				area.setText(null);
				birthday.setText(null);
				age.setText(null);
				constellation.setText(null);
				animal.setText(null);
				CE.setText(null);
				sex.setText(null);
				coefficient.setText(null);
			}
		});

		this.send.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				/** 所有的判断都在这里面执行 */
				judgeBegin();// 开始判断
			}
		});

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 关闭按钮彻底关闭窗体
		this.setResizable(false);// 不可重设窗体大小
		this.setVisible(true);// 窗体可见
	}

	/**
	 * 开始判断函数
	 */
	public void judgeBegin() {
		// 获取输入的身份证号
		String IDnum = ID.getText();
		if (IDnum.length() == 15) {// 将15位身份证号转换成18位身份证号
			IDnum = IDnum.substring(0, 6) + "19" + IDnum.substring(6) + 0;
		}
		// 判断身份证号的正则表达式 要么15位 要么18位 最后一位可以为字母
		Pattern IDnumpattern = Pattern.compile("(\\d{14}[0-9a-zA-Z])|(\\d{17}[0-9a-zA-Z])");
		Matcher IDnumMatcher = IDnumpattern.matcher(IDnum);
		if (IDnumMatcher.matches()) {// 如何满足正则表达式
			showArea(IDnum);// 判断输入的身份证号的所属地址
			// 生日判定成功，才能执行其他部分，否则不显示
			if (showBirthday(IDnum)) {// 显示出生日期
				showAge(IDnum);// 显示年龄
				showConstellation(IDnum);// 显示星座
				showAnimal(IDnum);// 显示生肖
				showCE(IDnum);// 显示天干地支
				showSex(IDnum);// 显示性别
				showCoefficient(ID.getText());// 显示校验位
			}
		} else {
			javax.swing.JOptionPane.showMessageDialog(null, "输入的身份证号不符合标准格式！");
		}
	}

	/**
	 * 插入所属地区信息库
	 */
	@SuppressWarnings("static-access")
	public void areaInsert() {
		this.city.put(11, "北京市");
		this.city.put(12, "天津市");
		this.city.put(13, "河北省");
		this.city.put(14, "山西省");
		this.city.put(15, "内蒙古自治区");
		this.city.put(21, "辽宁省");
		this.city.put(22, "吉林省");
		this.city.put(23, "黑龙江省");
		this.city.put(31, "上海省");
		this.city.put(32, "江苏省");
		this.city.put(33, "浙江省");
		this.city.put(34, "安徽省");
		this.city.put(35, "福建省");
		this.city.put(36, "江西省");
		this.city.put(37, "山东省");
		this.city.put(41, "河南省");
		this.city.put(42, "湖北省");
		this.city.put(43, "湖南省");
		this.city.put(44, "广东省");
		this.city.put(45, "广西壮族自治区");
		this.city.put(46, "海南省");
		this.city.put(50, "重庆市");
		this.city.put(51, "四川省");
		this.city.put(52, "贵州省");
		this.city.put(53, "云南省");
		this.city.put(54, "西藏自治区");
		this.city.put(61, "陕西省");
		this.city.put(62, "甘肃省");
		this.city.put(63, "青海省");
		this.city.put(64, "宁夏回族自治区");
		this.city.put(65, "新疆维吾尔自治区");
		this.city.put(71, "台湾省");
		this.city.put(81, "香港特别行政区");
		this.city.put(82, "澳门特别行政区");
	}

	/**
	 * 显示所属地区
	 */
	public void showArea(String str) {
		if (str.length() == 15 || str.length() == 18) {// 判断是否为15或18位，不是不判断
			String home = this.city.get(new Integer(str.substring(0, 2)));// 查询所属城市，如果查不到为null
			if (home != null) {
				this.area.setText(home);
			} else {
				this.area.setText("不存在");
			}
		} else {
			this.area.setText("不存在");
		}
	}

	/**
	 * 判断当前年份下，当前月下有多少天，区分平闰年
	 */
	public int getDays(int year, int month) {// 判断当前年份下，当前月下有多少天，区分平闰年
		if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {// 这些月下，不管是平年，还是闰年，都是31天
			return 31;
		} else if (month == 4 || month == 6 || month == 9 || month == 11) {// 这些月下，不管是平年，还是闰年，都是30天
			return 30;
		} else {
			if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {// 这是闰年
				return 29;
			} else { // 这是平年
				return 28;
			}
		}
	}

	/**
	 * 显示出生日期
	 */
	public boolean showBirthday(String str) {
		int year = Integer.valueOf(str.substring(6, 10));
		int month = Integer.valueOf(str.substring(10, 12));
		int day = Integer.valueOf(str.substring(12, 14));
		if (year > 0) {// 年份必须是大于0的
			if (month > 0 && month <= 12) {// 月必须大于0，月小于13，日还要单独算
				if (day > 0) {// 这里只判定大于0，小于多少，单独判定，因为年份月份不同，天数不同
					int days = getDays(year, month);// 判断当前年份下，当前月下有多少天，区分平闰年
					if (day <= days) {
						birthday.setText(year + "年" + month + "月" + day + "日");
						return true;
					} else {
						birthday.setText("不存在，具体几日有问题。");
					}
				} else {
					birthday.setText("不存在，具体几日有问题。");
				}
			} else {
				birthday.setText("不存在，具体几月有问题。");
			}
		} else {
			birthday.setText("不存在，具体哪一年有问题。");
		}
		return false;
	}

	/**
	 * 显示年龄
	 */
	public void showAge(String str) {
		int year = Integer.valueOf(str.substring(6, 10));
		int now = Calendar.getInstance().get(Calendar.YEAR);
		age.setText(String.valueOf(now - year));
	}

	/**
	 * 显示星座
	 */
	public void showConstellation(String str) {
		int month = Integer.valueOf(str.substring(10, 12));
		int day = Integer.valueOf(str.substring(12, 14));
		if ((month == 1 && day >= 20) || (month == 2 && day <= 18)) {
			constellation.setText("窝是 水瓶座 哇咔咔");
		} else if ((month == 2 && day >= 19) || (month == 3 && day <= 20)) {
			constellation.setText("我是 双鱼座 么么哒");
		} else if ((month == 3 && day > 20) || (month == 4 && day <= 19)) {
			constellation.setText("白羊座 咩咩咩");
		} else if ((month == 4 && day >= 20) || (month == 5 && day <= 20)) {
			constellation.setText("金牛座 哞哞哞");
		} else if ((month == 5 && day >= 21) || (month == 6 && day <= 21)) {
			constellation.setText("双子座  (*^__^*) 嘻嘻……");
		} else if ((month == 6 && day > 21) || (month == 7 && day <= 22)) {
			constellation.setText("巨蟹座 我擦擦");
		} else if ((month == 7 && day > 22) || (month == 8 && day <= 22)) {
			constellation.setText("狮子座 咬我呀");
		} else if ((month == 8 && day >= 23) || (month == 9 && day <= 22)) {
			constellation.setText("处女座  好羞射");
		} else if ((month == 9 && day >= 23) || (month == 10 && day <= 23)) {
			constellation.setText("天秤座 嘿嘿嘿");
		} else if ((month == 10 && day > 23) || (month == 11 && day <= 22)) {
			constellation.setText("天蝎座 我有毒");
		} else if ((month == 11 && day > 22) || (month == 12 && day <= 21)) {
			constellation.setText("射手座 最花心");
		} else if ((month == 12 && day > 21) || (month == 1 && day <= 19)) {
			constellation.setText("魔羯座  呃呃呃");
		} else {
			;
		}
	}

	/**
	 * 显示生肖
	 */
	public void showAnimal(String str) {
		int year = Integer.valueOf(str.substring(6, 10));
		String an[] = {"猪", "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗"};
		int end = 3;
		int x = (year - end) % 12;
		animal.setText(an[x]);
	}

	/**
	 * 显示天干地支
	 */
	public void showCE(String str) {
		int year = Integer.valueOf(str.substring(6, 10));
		String a[] = {"癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "任"};
		String b[] = {"亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌"};
		int i = (year - 3) % 10;
		int j = (year - 3) % 12;
		CE.setText(a[i] + b[j]);
	}

	/**
	 * 显示性别
	 */
	public void showSex(String str) {
		sex.setText(((Integer.valueOf(str.substring(16, 17))) % 2 == 1 ? "是个老爷们" : "是个老娘们"));
	}

	/**
	 * 获取身份证校验码，参数是身份证字符串，返回值-1代表的是"x"或"X"
	 */
	public int getCheck(String str) {
		/** 这个变量用来存放所有校验和 */
		int sum = 0;
		/** 这个数组里面存放的是身份证校验位系数，coefficient的缩写 */
		int[] coe = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
		/** 这个数组里面存放的是身份证校验对应的最后一位身份证号码 */
		int[] check = {1, 0, -1, 9, 8, 7, 6, 5, 4, 3, 2};// -1代表的是"x"或"X"
		for (int i = 0; i < str.length() - 1; i++) {
			sum = sum + Integer.parseInt(str.charAt(i) + "") * coe[i];
		}
		return check[sum % 11];
	}

	/**
	 * 显示校验位
	 */
	public void showCoefficient(String str) {// 这个模块是用来显示校验码是否正确的
		int last = getCheck(str);// 存放最后一位计算出来的值，用于和输入的值进行比较
		if (str.length() != 18) {
			coefficient.setText("15位身份证，没有校验位。");
		} else {
			if ((str.substring(17, 18) + "").equals(String.valueOf(last))
					|| (str.substring(17).equals("x") && last == -1)
					|| (str.substring(17).equals("X") && last == -1)) {// 比较最后一位是否和计算的值一致
				coefficient.setText("校验位正确。");
			} else {
				coefficient.setText("校验位错误，应是：" + ((last != -1) ? last : "x"));
			}
		}
	}
}
